// FIT_6204_Gorodilov_TrSegView.cpp : implementation of the CFIT_6204_Gorodilov_TrSegView class
//

#include "stdafx.h"
#include "FIT_6204_Gorodilov_TrSeg.h"

#include "FIT_6204_Gorodilov_TrSegDoc.h"
#include "FIT_6204_Gorodilov_TrSegView.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#endif


// CFIT_6204_Gorodilov_TrSegView

IMPLEMENT_DYNCREATE(CFIT_6204_Gorodilov_TrSegView, CScrollView)

BEGIN_MESSAGE_MAP(CFIT_6204_Gorodilov_TrSegView, CScrollView)
	ON_WM_ERASEBKGND()
	ON_WM_SIZE()
	ON_WM_LBUTTONDOWN()
	ON_WM_MOUSEMOVE()
	ON_COMMAND(ID_VIEW_MESH, &CFIT_6204_Gorodilov_TrSegView::OnViewMesh)
	ON_UPDATE_COMMAND_UI(ID_VIEW_MESH, &CFIT_6204_Gorodilov_TrSegView::OnUpdateViewMesh)
	ON_COMMAND(ID_EDIT_RUN, &CFIT_6204_Gorodilov_TrSegView::OnEditRun)
END_MESSAGE_MAP()

// CFIT_6204_Gorodilov_TrSegView construction/destruction

CFIT_6204_Gorodilov_TrSegView::CFIT_6204_Gorodilov_TrSegView()
: m_pDC(NULL)
, m_pBitmap(NULL)
, m_pOldBitmap(NULL)
, m_bIsDrawMesh(true)
, m_iMeshSize(10)
{
	m_pPointPen = new CPen(0, 0, RGB(0,128,255));
	m_pPointBrush = new CBrush(RGB(0,128,155));
	m_pPointBrushPeeked = new CBrush(RGB(255,0,0));
	m_pPointBrushFocused = new CBrush(RGB(0,255,10));
	m_pLinePen = new CPen(0, 2, RGB(255, 0, 55));
	m_pLinePen2 = new CPen(0, 0, RGB(0, 0, 0));
	m_pLinePen3 = new CPen(0, 0, RGB(180,180,90));
	m_pLinePen4 = new CPen(0, 4, RGB(200,130,40));
}

CFIT_6204_Gorodilov_TrSegView::~CFIT_6204_Gorodilov_TrSegView()
{
	if (m_pDC) {
		if (m_pOldBitmap) {
			m_pDC->SelectObject(m_pOldBitmap);
			m_pOldBitmap = NULL;
		}
		delete m_pDC;
	}
	if (m_pBitmap) {
		delete m_pBitmap;
	}
	if (m_pPointBrush) {
		delete m_pPointBrush;
	}
	if (m_pPointPen) {
		delete m_pPointPen;
	}
	if (m_pLinePen) {
		delete m_pLinePen;
	}
	if (m_pLinePen2) {
		delete m_pLinePen2;
	}
	if (m_pLinePen3) {
		delete m_pLinePen3;
	}
	if (m_pLinePen4) {
		delete m_pLinePen4;
	}
	if (m_pPointBrushPeeked) {
		delete m_pPointBrushPeeked;
	}
	if (m_pPointBrushFocused) {
		delete m_pPointBrushFocused;
	}
}

BOOL CFIT_6204_Gorodilov_TrSegView::PreCreateWindow(CREATESTRUCT& cs)
{
	// TODO: Modify the Window class or styles here by modifying
	//  the CREATESTRUCT cs

	return CScrollView::PreCreateWindow(cs);
}

// CFIT_6204_Gorodilov_TrSegView drawing

void CFIT_6204_Gorodilov_TrSegView::OnDraw(CDC* pDC)
{
	CFIT_6204_Gorodilov_TrSegDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);
	if (!pDoc)
		return;

	CSize lScrollSize = pDoc->GetScrollSize();
	CRect clientRect;
	GetClientRect(&clientRect);
	int width = lScrollSize.cx;
	int height = lScrollSize.cy;
	if (clientRect.right - clientRect.left > width) {
		width = clientRect.right - clientRect.left;
	}
	if (clientRect.bottom - clientRect.top > height) {
		height = clientRect.bottom - clientRect.top;
	}

	m_pDC->FillSolidRect(0, 0, 
		width, height,
		RGB(50,50,50));

	m_pDC->FillSolidRect(0, 0, 
		lScrollSize.cx, lScrollSize.cy,
		RGB(250,250,210));


	if (m_bIsDrawMesh) {
		CPen *pOldPen = m_pDC->SelectObject(m_pLinePen3);
		for (int x = 0; x < lScrollSize.cx; x += m_iMeshSize) {
			m_pDC->MoveTo(x, 0);
			m_pDC->LineTo(x, lScrollSize.cy);
		}
		for (int y = 0; y < lScrollSize.cy; y += m_iMeshSize) {
			m_pDC->MoveTo(0, y);
			m_pDC->LineTo(lScrollSize.cx, y);
		}
		m_pDC->SelectObject(pOldPen);
	}

	CPoint radiusPoint(3,3);

	CPen *pOldPen = m_pDC->SelectObject(m_pPointPen);
	CBrush *pOldBrush = m_pDC->SelectObject(m_pPointBrush);
	
	INT_PTR count = pDoc->m_aRects.GetCount();
	for (INT_PTR index = 0; index < count; index++) {
		CFIT_6204_Gorodilov_Rect rectItem = pDoc->m_aRects.GetAt(index);
		CFIT_6204_Gorodilov_Point &left = rectItem.left();
		CFIT_6204_Gorodilov_Point &right = rectItem.right();
		CRect rect(x(left.x()), y(left.top()), x(right.x()), y(right.bottom()));
		CPen *pOldLinePen = m_pDC->SelectObject(m_pLinePen);
			
		CPoint points[5];
		points[0] = CPoint(rect.left, rect.bottom);
		points[1] = CPoint(rect.left, rect.top);
		points[2] = CPoint(rect.right, rect.top);
		points[3] = CPoint(rect.right, rect.bottom);
		points[4] = CPoint(rect.left, rect.bottom);
		m_pDC->Polyline(points, 5);
		m_pDC->SelectObject(pOldLinePen);

		CRect rectP((CPoint)(radiusPoint),
			CSize(radiusPoint.x*2, radiusPoint.y*2));
		for (int i = 0; i < 5; i++) {
			rectP.MoveToXY((CPoint)(points[i]- radiusPoint));
			m_pDC->Ellipse(rectP);
		}		
	}

	if (!pDoc->m_bIsFirstPoint) {
		m_pCurPoint2 = m_pMousePoint;
		CFIT_6204_Gorodilov_Rect rectItem;
		CFIT_6204_Gorodilov_Point &left = rectItem.left();
		CFIT_6204_Gorodilov_Point &right = rectItem.right();
		left.x() = __min(m_pCurPoint.x, m_pCurPoint2.x);
		double& tl = left.top();
		double& bl = left.bottom();
		tl = __max(m_pCurPoint.y, m_pCurPoint2.y);
		bl = __min(m_pCurPoint.y, m_pCurPoint2.y);
		double& tr = right.top();
		double& br = right.bottom();
		right.x() = __max(m_pCurPoint.x, m_pCurPoint2.x);
		tr = __max(m_pCurPoint.y, m_pCurPoint2.y);
		br = __min(m_pCurPoint.y, m_pCurPoint2.y);
		
		CRect rect(x(left.x()), y(left.top()), x(right.x()), y(right.bottom()));
		CPen *pOldLinePen = m_pDC->SelectObject(m_pLinePen);

		CPoint points[5];
		points[0] = CPoint(rect.left, rect.bottom);
		points[1] = CPoint(rect.left, rect.top);
		points[2] = CPoint(rect.right, rect.top);
		points[3] = CPoint(rect.right, rect.bottom);
		points[4] = CPoint(rect.left, rect.bottom);
		m_pDC->Polyline(points, 5);
		m_pDC->SelectObject(pOldLinePen);

		CRect rectP((CPoint)(radiusPoint),
			CSize(radiusPoint.x*2, radiusPoint.y*2));
		for (int i = 0; i < 5; i++) {
			rectP.MoveToXY((CPoint)(points[i]- radiusPoint));
			m_pDC->Ellipse(rectP);
		}		
	}

	INT_PTR count1 = pDoc->m_aBoundVert.GetCount();
	for (INT_PTR index = 0; index < count1; index++) {
		CFIT_6204_Gorodilov_Point point = pDoc->m_aBoundVert.GetAt(index);
		CPen *pOldPen = m_pDC->SelectObject(m_pLinePen4);
		m_pDC->MoveTo(x(point.x()), y(point.top()));
		m_pDC->LineTo(x(point.x()), y(point.bottom()));
		m_pDC->SelectObject(pOldPen);
	}

	INT_PTR count2 = pDoc->m_aBoundHor.GetCount();
	for (INT_PTR index = 0; index < count2; index++) {
		CFIT_6204_Gorodilov_Point point = pDoc->m_aBoundHor.GetAt(index);
		CPen *pOldPen = m_pDC->SelectObject(m_pLinePen4);
		m_pDC->MoveTo(x(point.top()), y(point.x()));
		m_pDC->LineTo(x(point.bottom()), y(point.x()));
		m_pDC->SelectObject(pOldPen);
	}

	CRect rectP((CPoint)(radiusPoint),
		CSize(radiusPoint.x*2, radiusPoint.y*2));

	CPoint pointLoc = m_pMousePoint;
	pointLoc.y = pDoc->GetScrollSize().cy - pointLoc.y;
	rectP.MoveToXY((CPoint)(pointLoc - radiusPoint));
	m_pDC->Ellipse(rectP);

	m_pDC->SelectObject(pOldPen);
	m_pDC->SelectObject(pOldBrush);

	pDC->BitBlt(0, 0,
		width, height,
		m_pDC,0,0,SRCCOPY);
}

void CFIT_6204_Gorodilov_TrSegView::OnInitialUpdate()
{
	CScrollView::OnInitialUpdate();

	CFIT_6204_Gorodilov_TrSegDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);
	if (!pDoc)
		return;

	CSize lScrollSize = pDoc->GetScrollSize();

	SetScrollSizes(MM_TEXT, lScrollSize);
	if (m_pDC) {
		if (m_pOldBitmap) {
			m_pDC->SelectObject(m_pOldBitmap);
			m_pOldBitmap = NULL;
		}
		delete m_pDC;
	}
	if (m_pBitmap) {
		delete m_pBitmap;
	}

	m_pDC = new CDC();
	m_pDC->CreateCompatibleDC(GetDC());

	int width = lScrollSize.cx;
	int height = lScrollSize.cy;
	CRect clientRect;
	GetClientRect(&clientRect);
	if (clientRect.right - clientRect.left > width) {
		width = clientRect.right - clientRect.left;
	}
	if (clientRect.bottom - clientRect.top > height) {
		height = clientRect.bottom - clientRect.top;
	}
	m_pBitmap = new CBitmap();
	if (m_pBitmap->CreateCompatibleBitmap(GetDC(),
		width, height)) {
			m_pOldBitmap = m_pDC->SelectObject(m_pBitmap);
	}
}


// CFIT_6204_Gorodilov_TrSegView diagnostics

#ifdef _DEBUG
void CFIT_6204_Gorodilov_TrSegView::AssertValid() const
{
	CScrollView::AssertValid();
}

void CFIT_6204_Gorodilov_TrSegView::Dump(CDumpContext& dc) const
{
	CScrollView::Dump(dc);
}

CFIT_6204_Gorodilov_TrSegDoc* CFIT_6204_Gorodilov_TrSegView::GetDocument() const // non-debug version is inline
{
	ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CFIT_6204_Gorodilov_TrSegDoc)));
	return (CFIT_6204_Gorodilov_TrSegDoc*)m_pDocument;
}
#endif //_DEBUG


// CFIT_6204_Gorodilov_TrSegView message handlers

BOOL CFIT_6204_Gorodilov_TrSegView::OnEraseBkgnd(CDC* /*pDC*/)
{
	return TRUE;
}

void CFIT_6204_Gorodilov_TrSegView::OnSize(UINT nType, int cx, int cy)
{
	CScrollView::OnSize(nType, cx, cy);

	OnInitialUpdate();
}

int CFIT_6204_Gorodilov_TrSegView::x(double dx) {
	CFIT_6204_Gorodilov_TrSegDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);
	if (!pDoc)
		return 0;

	CSize size = pDoc->GetScrollSize();
	int result = static_cast<int>(dx);
	result = __min(size.cx, result);
	result = __max(0, result);

	return result;
}

int CFIT_6204_Gorodilov_TrSegView::y(double dy) {
	CFIT_6204_Gorodilov_TrSegDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);
	if (!pDoc)
		return 0;

	CSize size = pDoc->GetScrollSize();
	int result = static_cast<int>(size.cy - dy);
	result = __min(size.cy, result);
	result = __max(0, result);

	return result;
}
void CFIT_6204_Gorodilov_TrSegView::OnLButtonDown(UINT nFlags, CPoint point)
{
	CFIT_6204_Gorodilov_TrSegDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);
	if (!pDoc)
		return;

	CPoint curPoint = point + GetScrollPosition();

	if (pDoc->m_bIsFirstPoint) {
		m_pCurPoint = curPoint;
		m_pCurPoint.y = pDoc->GetScrollSize().cy - m_pCurPoint.y;
		m_pCurPoint.x = (int)((double)m_pCurPoint.x / m_iMeshSize + 0.5) * m_iMeshSize;
		m_pCurPoint.y = (int)((double)m_pCurPoint.y / m_iMeshSize + 0.5) * m_iMeshSize;
		pDoc->m_bIsFirstPoint = false;
	} else {
		m_pCurPoint2 = curPoint;
		m_pCurPoint2.y = pDoc->GetScrollSize().cy - m_pCurPoint2.y;
		m_pCurPoint2.x = (int)((double)m_pCurPoint2.x / m_iMeshSize + 0.5) * m_iMeshSize;
		m_pCurPoint2.y = (int)((double)m_pCurPoint2.y / m_iMeshSize + 0.5) * m_iMeshSize;
		CFIT_6204_Gorodilov_Rect rect;
		CFIT_6204_Gorodilov_Point &left = rect.left();
		CFIT_6204_Gorodilov_Point &right = rect.right();
		left.x() = __min(m_pCurPoint.x, m_pCurPoint2.x);
		double& tl = left.top();
		double& bl = left.bottom();
		tl = __max(m_pCurPoint.y, m_pCurPoint2.y);
		bl = __min(m_pCurPoint.y, m_pCurPoint2.y);
		double& tr = right.top();
		double& br = right.bottom();
		right.x() = __max(m_pCurPoint.x, m_pCurPoint2.x);
		tr = __max(m_pCurPoint.y, m_pCurPoint2.y);
		br = __min(m_pCurPoint.y, m_pCurPoint2.y);
		pDoc->m_aRects.Add(rect);
		pDoc->m_bIsFirstPoint = true;
		Invalidate();
	}

	CScrollView::OnLButtonDown(nFlags, point);
}

void CFIT_6204_Gorodilov_TrSegView::OnMouseMove(UINT nFlags, CPoint point)
{
	CFIT_6204_Gorodilov_TrSegDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);
	if (!pDoc)
		return;

	m_pMousePoint = point + GetScrollPosition();
	m_pMousePoint.y = pDoc->GetScrollSize().cy - m_pMousePoint.y;
	m_pMousePoint.x = (int)((double)m_pMousePoint.x / m_iMeshSize + 0.5) * m_iMeshSize;
	m_pMousePoint.y = (int)((double)m_pMousePoint.y / m_iMeshSize + 0.5) * m_iMeshSize;

	CScrollView::OnMouseMove(nFlags, point);
	Invalidate();
}

void CFIT_6204_Gorodilov_TrSegView::OnViewMesh()
{
	m_bIsDrawMesh = !m_bIsDrawMesh;
}

void CFIT_6204_Gorodilov_TrSegView::OnUpdateViewMesh(CCmdUI *pCmdUI)
{
	pCmdUI->SetCheck(m_bIsDrawMesh);
}

void CFIT_6204_Gorodilov_TrSegView::OnEditRun()
{
	CFIT_6204_Gorodilov_TrSegDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);
	if (!pDoc)
		return;

	pDoc->Run();

	Invalidate();
}
